﻿using System.Security.Cryptography;
using System.Text;

namespace UnityMethods.Extend
{
    public static partial class Ext
    {
        #region MD5

        /// <summary>
        /// 计算字符串的MD5值
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>        
        public static string ToMD5_32(this string srcData)
        {
            try
            {
                if (!srcData.IsEmpty())
                {
                    MD5 md5 = MD5.Create();
                    return BitConverter.ToString(md5.ComputeHash(Encoding.GetEncoding("utf-8").GetBytes(srcData))).Replace("-", "");
                }
            }
            catch (Exception)
            {
            }

            return "";
        }

        /// <summary>
        /// 计算字符串的MD5值
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>        
        public static string ToMD5_16(this string srcData)
        {
            try
            {
                if (!srcData.IsEmpty())
                {
                    MD5 md5 = MD5.Create();
                    return BitConverter.ToString(md5.ComputeHash(Encoding.GetEncoding("utf-8").GetBytes(srcData)), 4, 8).Replace("-", "");
                }
            }
            catch (Exception)
            {
            }

            return "";
        }

        /// <summary>
        /// 获取文件的MD5
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static string GetMD5HashFromFile(string fileName)
        {
            using (FileStream file = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                MD5 md5 = MD5.Create();

                byte[] hash = md5.ComputeHash(file);

                return BitConverter.ToString(hash).Replace("-", "");
            }
        }


        #endregion

        /// <summary>
        /// DES加密
        /// </summary>
        /// <param name="data">需要加密的字符</param>
        /// <param name="sKey">8位密匙</param>
        /// <returns></returns>
        public static string DESEncrypt(this string data, string sKey)
        {
            try
            {
                DES des = DES.Create();
                byte[] inArray = Encoding.UTF8.GetBytes(data);
                des.Key = Encoding.UTF8.GetBytes(sKey.Substring(0, 8));// 密匙
                des.IV = Encoding.UTF8.GetBytes(sKey.Substring(0, 8));// 初始化向量
                des.Mode = CipherMode.ECB;
                des.Padding = PaddingMode.PKCS7;
                MemoryStream ms = new MemoryStream();
                CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
                cs.Write(inArray, 0, inArray.Length);
                cs.FlushFinalBlock();
                return Convert.ToBase64String(ms.ToArray());
            }
            catch (Exception ex)
            {
                return "";
            }
        }


        /// <summary>
        /// DES解密
        /// </summary>
        /// <param name="data">需要解密的字符</param>
        /// <param name="sKey">8位密匙</param>
        /// <returns></returns>
        public static string DESDecrypt(this string data, string sKey)
        {
            if (data.IsEmpty())
            {
                return "";
            }

            try
            {
                DES des = DES.Create();
                byte[] inputByteArray = Convert.FromBase64String(data);
                des.Key = Encoding.UTF8.GetBytes(sKey.Substring(0, 8));
                des.IV = Encoding.UTF8.GetBytes(sKey.Substring(0, 8));
                des.Mode = CipherMode.ECB;
                des.Padding = PaddingMode.PKCS7;
                MemoryStream ms = new MemoryStream();
                CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
                cs.Write(inputByteArray, 0, inputByteArray.Length);
                // 如果两次密匙不一样，这一步可能会引发异常
                cs.FlushFinalBlock();
                return Encoding.UTF8.GetString(ms.ToArray());
            }
            catch (Exception ex)
            {
                return "";
            }
        }

        /// <summary>
        /// 16进制字符串转字节数组
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static byte[] HexToBytes(String src)
        {
            int l = src.Length / 2;
            String str;
            byte[] ret = new byte[l];

            for (int i = 0; i < l; i++)
            {
                str = src.Substring(i * 2, 2);
                ret[i] = Convert.ToByte(str, 16);
            }
            return ret;
        }

        #region AES 加密解密

        /// <summary>
        /// 获取随机密码
        /// </summary>
        /// <param name="num"></param>
        /// <returns></returns>
        public static string GetRandomIv(int num)
        {
            char[] arrChar = new char[]
            {
                'a','b','d','c','e','f','g','h','i','j','k','l','m','n','p','r','q','s','t','u','v','w','z','y','x',
                '0','1','2','3','4','5','6','7','8','9',
                'A','B','C','D','E','F','G','H','I','J','K','L','M','N','Q','P','R','T','S','V','U','W','X','Y','Z'
            };

            StringBuilder str = new StringBuilder();
            Random rnd = new Random(DateTime.Now.Millisecond);
            for (int i = 0; i < num; i++)
            {
                str.Append(arrChar[rnd.Next(0, arrChar.Length)].ToString());
            }

            return str.ToString();
        }

        /// <summary>
        /// AES加密
        /// </summary>
        /// <param name="Data">被加密的明文</param>
        /// <param name="key">密钥</param>
        /// <returns>密文</returns>
        public static string AESEncrypt(this string Data, string key)
        {
            Byte[] plainBytes = Encoding.UTF8.GetBytes(Data);
            Byte[] bKey = new Byte[32];
            Array.Copy(Encoding.UTF8.GetBytes(key.PadRight(bKey.Length)), bKey, bKey.Length);
            Byte[] bVector = new Byte[16];
            Array.Copy(Encoding.UTF8.GetBytes(key.PadRight(bVector.Length)), bVector, bVector.Length);

            // 加密后的密文
            Byte[] Cryptograph = null;
            Aes aes = Aes.Create();
            aes.Mode = CipherMode.ECB;
            aes.Padding = PaddingMode.PKCS7;
            aes.BlockSize = 128;
            try
            {
                using (MemoryStream Memory = new MemoryStream())
                {
                    // 把内存流对象包装成加密流对象
                    using (CryptoStream Encryptor = new CryptoStream(Memory,
                    aes.CreateEncryptor(bKey, bVector),
                    CryptoStreamMode.Write))
                    {
                        // 明文数据写入加密流
                        Encryptor.Write(plainBytes, 0, plainBytes.Length);
                        Encryptor.FlushFinalBlock();
                        Cryptograph = Memory.ToArray();
                    }
                }

                return Convert.ToBase64String(Cryptograph);
            }
            catch (Exception)
            {
                return "";
            }

        }

        /// <summary>
        /// AES解密
        /// </summary>
        /// <param name="Data">被解密的密文</param>
        /// <param name="key">密钥</param>
        /// <param name="Vector">向量</param>
        /// <returns>明文</returns>
        public static string AESDecrypt(this string Data, string key)
        {
            Byte[] encryptedBytes = Convert.FromBase64String(Data);
            Byte[] bKey = new Byte[32];
            Array.Copy(Encoding.UTF8.GetBytes(key.PadRight(bKey.Length)), bKey, bKey.Length);
            Byte[] bVector = new Byte[16];
            Array.Copy(Encoding.UTF8.GetBytes(key.PadRight(bVector.Length)), bVector, bVector.Length);

            // 解密后的明文
            Byte[] original = null;
            Aes aes = Aes.Create();
            aes.Mode = CipherMode.ECB;
            aes.Padding = PaddingMode.PKCS7;
            aes.BlockSize = 128;
            try
            {
                // 开辟一块内存流，存储密文
                using (MemoryStream Memory = new MemoryStream(encryptedBytes))
                {
                    // 把内存流对象包装成加密流对象
                    using (CryptoStream Decryptor = new CryptoStream(Memory,
                    aes.CreateDecryptor(bKey, bVector),
                    CryptoStreamMode.Read))
                    {
                        // 明文存储区
                        using (MemoryStream originalMemory = new MemoryStream())
                        {
                            Byte[] Buffer = new Byte[1024];
                            Int32 readBytes = 0;
                            while ((readBytes = Decryptor.Read(Buffer, 0, Buffer.Length)) > 0)
                            {
                                originalMemory.Write(Buffer, 0, readBytes);
                            }
                            original = originalMemory.ToArray();
                        }
                    }
                }

                return Encoding.UTF8.GetString(original);
            }
            catch (Exception)
            {
                return "";
            }

        }

        #endregion
    }
}
